package com.lucifer.treasure.enchant.effect;

import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.minecraft.block.*;
import net.minecraft.enchantment.EnchantmentEffectContext;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.enchantment.EnchantmentLevelBasedValue;
import net.minecraft.enchantment.effect.EnchantmentEntityEffect;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.HoeItem;
import net.minecraft.item.ItemStack;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.World;
import net.minecraft.state.property.IntProperty;
import net.minecraft.state.property.Property;
import net.minecraft.registry.Registries;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public record GrowthEnchantmentEffect(EnchantmentLevelBasedValue range) implements EnchantmentEntityEffect {
    public static final MapCodec<GrowthEnchantmentEffect> CODEC = RecordCodecBuilder.mapCodec(instance ->
            instance.group(
                    EnchantmentLevelBasedValue.CODEC.fieldOf("range").forGetter(GrowthEnchantmentEffect::range)
            ).apply(instance, GrowthEnchantmentEffect::new)
    );

    // 配置常量
    private static final int RADIUS_FACTOR = 2;        // 每级增加的范围（到达上限后不再增加）
    private static final int MAX_RADIUS = 4;           // 最大水平半径=4 => 约 9x9 区域，贴近 8x8 需求
    private static final int LIMIT_FACTOR = 2;         // 每级增加的生长限制
    private static final int HEIGHT = 2;               // 垂直搜索范围
    private static final double GROWTH_ODDS = 0.15;    // 基础 15% 几率尝试催熟
    private static final int TICK_INTERVAL = 20;       // 每秒检查一次

    // 用于跟踪tick计数
    private static int tickCounter = 0;

    public static void initialize() {
        ServerTickEvents.END_SERVER_TICK.register(server -> {
            tickCounter++;
            if (tickCounter % TICK_INTERVAL != 0) {
                return; // 不是检查时机
            }

            server.getPlayerManager().getPlayerList().forEach(player -> {
                if (player.isSpectator() || !player.isAlive()) {
                    return;
                }

                // 支持主手与副手，取两手中携带的最高等级且为锄头的物品
                SelectedTool selected = getSelectedGrowthTool(player);
                if (selected.level <= 0) {
                    return;
                }

                // 执行生长逻辑（根据是否达到范围上限来切换为“速度提升”模式）
                boolean rangeCapped = computeRadius(selected.level) >= MAX_RADIUS;
                int growthStepHint = computeGrowthStepHint(selected.level, rangeCapped, player.getWorld().getRandom());
                int grown = growAroundPlayer(player, selected.level, growthStepHint);

                // 成功催熟则消耗对应手中工具耐久
                if (grown > 0) {
                    damageToolOnce(selected.stack);
                }
            });
        });
    }

    /**
     * 在玩家周围催熟作物
     */
    private static int growAroundPlayer(PlayerEntity player, int level, int growthStepHint) {
        World world = player.getWorld();
        if (!(world instanceof ServerWorld serverWorld)) {
            return 0;
        }

        // 计算生长限制（下雨时增加）
        int growthLimit = level * LIMIT_FACTOR + (world.isRaining() ? 4 : 0);

        // 计算搜索范围（达到上限后不再增加）
        int radius = computeRadius(level);

        // 获取玩家脚下位置
        BlockPos playerPos = player.getBlockPos();

        // 创建搜索区域
        List<BlockPos> positions = createSearchArea(playerPos, radius, HEIGHT);
        Collections.shuffle(positions); // 随机顺序

        Random random = world.getRandom();
        int grown = 0;

        for (BlockPos pos : positions) {
            if (grown >= growthLimit) {
                break;
            }

            if (tryGrowCrop(serverWorld, pos, random, growthStepHint)) {
                grown++;
            }
        }

        return grown;
    }

    /**
     * 创建搜索区域
     */
    private static List<BlockPos> createSearchArea(BlockPos center, int radius, int height) {
        List<BlockPos> positions = new ArrayList<>();

        for (int x = -radius; x <= radius; x++) {
            for (int z = -radius; z <= radius; z++) {
                for (int y = -1; y < height; y++) { // 从脚下开始向上搜索
                    positions.add(center.add(x, y, z));
                }
            }
        }

        return positions;
    }

    /**
     * 尝试催熟指定位置的作物
     */
    private static boolean tryGrowCrop(ServerWorld world, BlockPos pos, Random random, int growthStepHint) {
        if (random.nextDouble() > GROWTH_ODDS) {
            return false; // 概率检查失败
        }

        BlockState state = world.getBlockState(pos);
        Block block = state.getBlock();

        // 0) 明确排除：地形方块、花类、草类等不应生长的植物
        String blockId = Registries.BLOCK.getId(block).toString();
        if (isGroundLikeDisallowed(blockId) || isFloraDisallowed(block, blockId)) {
            return false;
        }

        // 1) 通用优先：任何实现了 Fertilizable 的植物（等同骨粉效果）
        if (block instanceof Fertilizable fertilizable) {
            try {
                // isFertilizable：当前位置该植物是否可被施肥
                if (fertilizable.isFertilizable(world, pos, state)) {
                    // canGrow：当前状态下是否还能继续生长
                    boolean any = false;
                    for (int i = 0; i < growthStepHint; i++) {
                        if (fertilizable.canGrow(world, world.random, pos, state)) {
                            fertilizable.grow(world, world.random, pos, state);
                            any = true;
                            // 取最新状态用于下一次判定
                            state = world.getBlockState(pos);
                        } else {
                            break;
                        }
                    }
                    if (any) { addGrowthParticles(world, pos); return true; }
                }
            } catch (Throwable t) {
                // 某些模组可能在实现上抛异常，吞并后继续尝试其他路径，确保不影响主流程
            }
        }

        // 检查是否是可以催熟的作物
        if (block instanceof CropBlock cropBlock) {
            // 普通作物（小麦、胡萝卜、土豆等）
            if (!cropBlock.isMature(state)) {
                int age = cropBlock.getAge(state);
                int maxAge = cropBlock.getMaxAge();

                if (age < maxAge) {
                    // 按照提示步进多阶段提升，但不超过最大年龄
                    int newAge = Math.min(maxAge, age + Math.max(1, growthStepHint));
                    BlockState newState = cropBlock.withAge(newAge);
                    world.setBlockState(pos, newState, Block.NOTIFY_LISTENERS);

                    // 添加粒子效果
                    addGrowthParticles(world, pos);
                    return true;
                }
            }
        } else if (block instanceof StemBlock) {
            // 南瓜茎和西瓜茎（仅限真正的茎类方块）
            int age = state.get(StemBlock.AGE);
            int maxAge = 7; // 茎的最大年龄

            if (age < maxAge) {
                int newAge = Math.min(maxAge, age + Math.max(1, growthStepHint));
                BlockState newState = state.with(StemBlock.AGE, newAge);
                world.setBlockState(pos, newState, Block.NOTIFY_LISTENERS);

                addGrowthParticles(world, pos);
                return true;
            }
        }
        
        // 3) 通用兜底：尝试识别 AGE 整数属性（适配甘蔗、仙人掌、可成长作物及大多数模组植物）
        IntProperty ageProperty = findAgeProperty(state);
        if (ageProperty != null) {
            Integer currentAge = state.get(ageProperty);
            int maxAge = getMaxValue(ageProperty);
            if (currentAge != null && currentAge < maxAge) {
                int newAge = Math.min(maxAge, currentAge + Math.max(1, growthStepHint));
                BlockState newState = state.with(ageProperty, newAge);
                world.setBlockState(pos, newState, Block.NOTIFY_LISTENERS);
                addGrowthParticles(world, pos);
                return true;
            }
        }
//        else if (block instanceof BlockWithEntity blockWithEntity) {
//            //cobblemon植物继承的基类
//            int age = state.get(StemBlock.AGE);
//            int maxAge = 7; // 茎的最大年龄
//
//            if (age < maxAge) {
//                int newAge = Math.min(maxAge, age + random.nextInt(2) + 1);
//                BlockState newState = state.with(StemBlock.AGE, newAge);
//                world.setBlockState(pos, newState, Block.NOTIFY_LISTENERS);
//
//                addGrowthParticles(world, pos);
//                return true;
//            }
//
//
//        }
        // 其他植物
        // 保守起见，不直接调用 randomTick，以避免与模组自定义逻辑冲突（例如需要环境检查/方块实体数据等）

        return false;
    }

    // 计算在当前等级下的水平半径（达到上限后不再增加）
    private static int computeRadius(int level) {
        return Math.min(MAX_RADIUS, 1 + level * RADIUS_FACTOR);
    }

    // 根据等级与是否达到了范围上限，计算推荐的单次提升阶段数（越高等级越容易更大步进）
    private static int computeGrowthStepHint(int level, boolean rangeCapped, Random random) {
        int baseMax = 2; // 原始逻辑约 1~2 阶
        int extraMax;
        if (rangeCapped) {
            // 达到范围上限后，显著提高步进上限与命中概率
            extraMax = Math.min(1 + level / 4, 6); // 最高再 +6 阶
        } else {
            // 未达范围上限，适度提升
            extraMax = Math.min(level / 6, 3);
        }
        int bound = Math.max(1, baseMax + extraMax);
        // 1..bound 的均匀分布，等级越高 bound 越大 => 更大步进概率更高
        return 1 + random.nextInt(bound);
    }

    // 查找两手中可用的最高等级 Growth 附魔锄头
    private static SelectedTool getSelectedGrowthTool(PlayerEntity player) {
        ItemStack main = player.getMainHandStack();
        ItemStack off = player.getOffHandStack();
        int mainLevel = (main.getItem() instanceof HoeItem) ? getGrowthLevelFromStack(main) : 0;
        int offLevel = (off.getItem() instanceof HoeItem) ? getGrowthLevelFromStack(off) : 0;
        if (offLevel > mainLevel) {
            return new SelectedTool(off, offLevel);
        }
        return new SelectedTool(main, mainLevel);
    }

    private record SelectedTool(ItemStack stack, int level) {}

    // 成功催熟后消耗耐久一次
    private static void damageToolOnce(ItemStack tool) {
        if (tool.isEmpty() || !tool.isDamageable()) return;
        tool.setDamage(tool.getDamage() + 1);
        if (tool.getDamage() >= tool.getMaxDamage()) {
            tool.setCount(0);
        }
    }

    /**
     * 判断是否为不应生效的地形方块（泥土、沙子、碎石、石头等）。
     * 采用注册名判断，避免引用不稳定的标签常量导致编译问题。
     */
    private static boolean isGroundLikeDisallowed(String blockId) {
        // 原版地表/地形类黑名单
        return blockId.equals("minecraft:dirt") ||
                blockId.equals("minecraft:grass_block") ||
                blockId.equals("minecraft:coarse_dirt") ||
                blockId.equals("minecraft:rooted_dirt") ||
                blockId.equals("minecraft:podzol") ||
                blockId.equals("minecraft:mud") ||
                blockId.equals("minecraft:clay") ||
                blockId.equals("minecraft:sand") ||
                blockId.equals("minecraft:red_sand") ||
                blockId.equals("minecraft:gravel") ||
                blockId.equals("minecraft:stone") ||
                blockId.equals("minecraft:cobblestone") ||
                blockId.equals("minecraft:deepslate") ||
                blockId.equals("minecraft:netherrack") ||
                blockId.equals("minecraft:end_stone") ||
                blockId.equals("minecraft:farmland");
    }

    /**
     * 拦截鲜花、双高花、草、蕨类、枯灌木等。
     * 同时用注册ID兜底涵盖模组花草（例如包含 "flower"、"tall_grass"、"fern" 等关键字）。
     */
    private static boolean isFloraDisallowed(Block block, String blockId) {
        // 明确类型：所有 FlowerBlock、TallPlantBlock、DeadBushBlock、Fern/Grass 类
        if (block instanceof FlowerBlock ||
                block instanceof TallPlantBlock ||
                block instanceof DeadBushBlock ||
                block instanceof GrassBlock) {
            return true;
        }

        // 注册ID关键词判定，兼容各类模组
        String id = blockId.toLowerCase();
        if (id.contains("flower") || id.contains("tall_flower") || id.contains("poppy") || id.contains("dandelion") ||
                id.contains("allium") || id.contains("blue_orchid") || id.contains("cornflower") || id.contains("oxeye_daisy") ||
                id.contains("azure_bluet") || id.contains("lily_of_the_valley") || id.contains("peony") || id.contains("rose_bush") ||
                id.contains("lilac") || id.contains("sunflower") || id.contains("tulip") ||
                id.contains("grass") || id.contains("tall_grass") || id.contains("fern") || id.contains("large_fern") ||
                id.contains("dead_bush")) {
            return true;
        }
        return false;
    }

    /**
     * 在 BlockState 中查找名为 "age" 的 IntProperty（忽略大小写），如果找不到，则尝试包含 "age" 的属性。
     */
    private static IntProperty findAgeProperty(BlockState state) {
        IntProperty candidateContains = null;
        for (Property<?> prop : state.getProperties()) {
            if (prop instanceof IntProperty intProp) {
                String name = prop.getName();
                if ("age".equalsIgnoreCase(name)) {
                    return intProp;
                }
                if (name.toLowerCase().contains("age")) {
                    candidateContains = intProp; // 先记录，若没有精确匹配再回退到包含匹配
                }
            }
        }
        return candidateContains;
    }

    /**
     * 获取 IntProperty 的最大可取值。
     */
    private static int getMaxValue(IntProperty property) {
        int max = Integer.MIN_VALUE;
        for (Integer v : property.getValues()) {
            if (v > max) max = v;
        }
        return max == Integer.MIN_VALUE ? 0 : max;
    }

    /**
     * 添加生长粒子效果
     */
    private static void addGrowthParticles(ServerWorld world, BlockPos pos) {
        // 在作物周围生成骨粉粒子效果
        world.spawnParticles(
                net.minecraft.particle.ParticleTypes.HAPPY_VILLAGER,
                pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5,
                3, // 粒子数量
                0.2, 0.2, 0.2, // 扩散范围
                0.02 // 速度
        );
    }

    /**
     * 从物品栈获取Growth附魔等级
     */
    private static int getGrowthLevelFromStack(ItemStack stack) {
        if (stack.isEmpty()) {
            return 0;
        }

        var enchantments = EnchantmentHelper.getEnchantments(stack);
        int maxLevel = 0;

        for (var entry : enchantments.getEnchantments()) {
            if (entry.getKey().isPresent()) {
                String enchantmentId = entry.getKey().get().getValue().toString();
                if (enchantmentId.equals("lucifer_treasure:growth")) {
                    maxLevel = Math.max(maxLevel, enchantments.getLevel(entry));
                }
            }
        }

        return maxLevel;
    }

    @Override
    public void apply(ServerWorld world, int level, EnchantmentEffectContext context, Entity target, Vec3d pos) {
        // 主要逻辑在服务器tick事件中处理
        // 这个方法保留用于其他可能的触发方式
    }

    @Override
    public MapCodec<? extends EnchantmentEntityEffect> getCodec() {
        return CODEC;
    }
} 